package com.ac.config;

import com.alibaba.fastjson.JSONObject;
import com.base.annotation.SysLog;
import com.base.context.Context;
import com.base.context.ContextHolder;
import com.base.context.IUser;
import com.base.helper.Result;
import com.ac.api.log.entity.AcLog;
import com.ac.api.log.service.AcLogService;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.Date;

/**
 *
 */
@Aspect
@Component
@Order(1)
public class WebLogAspect {

    private Logger logger = LoggerFactory.getLogger(WebLogAspect.class);

    private ThreadLocal<Long> startTime = new ThreadLocal<>();

    @Resource
    private AcLogService acLogService;

    @Pointcut("execution(public * com.ac.api.*.controller.*.*(..))")
    public void webLog() {
    }

    @Before("webLog()")
    public void doBefore(JoinPoint joinPoint){
        startTime.set(System.currentTimeMillis());
        // 接收到请求，记录请求内容
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest       request    = attributes.getRequest();
        // 记录下请求内容
        logger.info("URL : " + request.getRequestURL().toString());
        logger.info("HTTP_METHOD : " + request.getMethod());
        logger.info("IP : " + request.getRemoteAddr());
        logger.info("CLASS_METHOD : " + joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName());

    }

    @AfterReturning(returning = "result", pointcut = "webLog()")
    public void doAfterReturning(JoinPoint joinPoint, Result result) {
        /** 处理完请求，返回内容 */
        logger.info("RESPONSE : " + result.toString());
        logger.info("SPEND TIME : " + (System.currentTimeMillis() - startTime.get()));
        // 添加系统操作日志
        addLog(joinPoint, result);
    }

    private void addLog(JoinPoint joinPoint, Result result) {
        /** 接收到请求，记录请求内容  */
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest       request    = attributes.getRequest();
        /** 请求参数 */
        Object[] args   = joinPoint.getArgs();
        String   params = "";
        if (args != null && args.length > 0) {
            try {
                params = JSONObject.toJSONString(args[0]);
            } catch (Exception e) {
                params = "";
            }
        }
        MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
        Method          targetMethod    = methodSignature.getMethod();
        SysLog          sysLog          = targetMethod.getAnnotation(SysLog.class);
        if (sysLog != null) {
            Context context     = ContextHolder.currentContext();
            AcLog   log         = new AcLog();
                log.setAcoperator(0);
                log.setUsername("用户");
                log.setGrouptype("用户");
                log.setUsergroup("用户");
            log.setIpaddress(request.getRemoteAddr());
            log.setAction(sysLog.action());
            log.setActype(joinPoint.getSignature().getName());
            log.setCreatetime(new Date());
            log.setDescription(sysLog.value());
            log.setParams(params);
            log.setAcresult(result.isSuccess() ? "success" : "fail");
            String errorMsg = result.getErrorMsg();
            log.setError(errorMsg != null ?
                    errorMsg.substring(0, Math.min(errorMsg.length(), 2000)) :
                    null);
        }
    }

}
